#if defined(_WIN32) || defined(WIN32) 
#define OS_WIN
#endif

#ifdef OS_WIN


#undef UNICODE

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>

// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")
// #pragma comment (lib, "Mswsock.lib")

#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "5678"


#include <conio.h>
SOCKET ListenSocket = INVALID_SOCKET,
	ClientSocket = INVALID_SOCKET, ClientTwoSocket=INVALID_SOCKET;

DWORD WINAPI ThreadFunc(LPVOID lpParam) {
	// Do stuff.  This will be the first funciton called on the new thread.
	//int running=1;
	char recvbuf[DEFAULT_BUFLEN];
	int     Data = 0;
	int iResult=0;
	int iSendResult;
	Data = *((int*)lpParam); 


	// Receive until the peer shuts down the connection
	if(Data==1){
		do {
			iResult = recv(ClientSocket, recvbuf, DEFAULT_BUFLEN, 0);
			if (iResult > 0) {
				printf("Socket1 - Bytes received: %d\n", iResult);
				printf("Socket1 - Received:%s\n",recvbuf);
				// Echo the buffer back to the sender

				//string tokenizer by \0?

				iSendResult = send( ClientTwoSocket, recvbuf, iResult, 0 );
				if (iSendResult == SOCKET_ERROR) {
					printf("Socket1 - send failed with error: %d\n", WSAGetLastError());
					closesocket(ClientSocket);
					WSACleanup();
					return 1;
				}
				printf("Socket2 - Sent:%s\n",recvbuf);
				printf("Socket2 - Bytes sent: %d\n", iSendResult);
			}
			else if (iResult == 0)
				printf("Socket1 - Connection closing...\n");
			else  {
				printf("Socket1 - recv failed with error: %d\n", WSAGetLastError());
				closesocket(ClientSocket);
				WSACleanup();
				return 1;
			}



		} while (iResult > 0);	

		// shutdown the connection since we're done
		iResult = shutdown(ClientSocket, SD_SEND);
		if (iResult == SOCKET_ERROR) {
			printf("Socket1 - shutdown failed with error: %d\n", WSAGetLastError());
			closesocket(ClientSocket);
			WSACleanup();
			return 1;
		}

		// cleanup
		closesocket(ClientSocket);
		WSACleanup();

	}
	else{
		do {
			iResult = recv(ClientTwoSocket, recvbuf, DEFAULT_BUFLEN, 0);
			if (iResult > 0) {
				printf("Socket2 - Bytes received: %d\n", iResult);
				printf("Socket2 - Received:%s\n",recvbuf);
				// Echo the buffer back to the sender
				iSendResult = send( ClientSocket, recvbuf, iResult, 0 );
				if (iSendResult == SOCKET_ERROR) {
					printf("Socket2 - send failed with error: %d\n", WSAGetLastError());
					closesocket(ClientSocket);
					WSACleanup();
					return 1;
				}
				printf("Socket1 - Sent:%s\n",recvbuf);
				printf("Socket1 - Bytes sent: %d\n", iSendResult);
			}
			else if (iResult == 0)
				printf("Socket2 - Connection closing...\n");
			else  {
				printf("Socket2 - recv failed with error: %d\n", WSAGetLastError());
				closesocket(ClientTwoSocket);
				WSACleanup();
				return 1;
			}



		} while (iResult > 0);	


		// shutdown the connection since we're done
		iResult = shutdown(ClientTwoSocket, SD_SEND);
		if (iResult == SOCKET_ERROR) {
			printf("Socket2 - shutdown failed with error: %d\n", WSAGetLastError());
			closesocket(ClientTwoSocket);
			WSACleanup();
			return 1;
		}

		// cleanup
		closesocket(ClientTwoSocket);
		WSACleanup();

	}



	// When this function returns, the thread goes away.  See MSDN for more details.
	return 0;
}




int __cdecl main(void) 
{
	WSADATA wsaData;

	struct addrinfo *result = NULL,
		hints;
	char recvbuf[DEFAULT_BUFLEN];
	int iResult, iSendResult;


	// Initialize Winsock
	iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
	if (iResult != 0) {
		printf("WSAStartup failed with error: %d\n", iResult);
		return 1;
	}

	ZeroMemory(&hints, sizeof(hints));
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;
	hints.ai_flags = AI_PASSIVE;

	// Resolve the server address and port
	iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
	if ( iResult != 0 ) {
		printf("getaddrinfo failed with error: %d\n", iResult);
		WSACleanup();
		return 1;
	}

	// Create a SOCKET for connecting to server
	ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
	if (ListenSocket == INVALID_SOCKET) {
		printf("socket failed with error: %ld\n", WSAGetLastError());
		freeaddrinfo(result);
		WSACleanup();
		return 1;
	}

	// Setup the TCP listening socket
	iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);
	if (iResult == SOCKET_ERROR) {
		printf("bind failed with error: %d\n", WSAGetLastError());
		freeaddrinfo(result);
		closesocket(ListenSocket);
		WSACleanup();
		return 1;
	}

	freeaddrinfo(result);

	iResult = listen(ListenSocket, SOMAXCONN);
	if (iResult == SOCKET_ERROR) {
		printf("listen failed with error: %d\n", WSAGetLastError());
		closesocket(ListenSocket);
		WSACleanup();
		return 1;
	}

	// Accept a client socket, first player
	ClientSocket = accept(ListenSocket, NULL, NULL);
	if (ClientSocket == INVALID_SOCKET) {	
		printf("accept failed with error: %d\n", WSAGetLastError());
		closesocket(ListenSocket);
		WSACleanup();
		return 1;
	}
	printf("Client 1 Accepted\n");
	//second player
	ClientTwoSocket = accept(ListenSocket, NULL, NULL);
	if (ClientTwoSocket == INVALID_SOCKET) {	
		printf("accept failed with error: %d\n", WSAGetLastError());
		closesocket(ListenSocket);
		WSACleanup();
		return 1;
	}
	printf("Client 2 Accepted\n");

	// No longer need server socket
	closesocket(ListenSocket);
	//spawn a thread to listen to each client seperately
	//an argument to creating a thread will be 1 or 2


	int playerIDOne=1;
	int playerIDTwo=2;
	HANDLE threadOne = CreateThread(NULL, 0, ThreadFunc, &playerIDOne, 0, NULL);
	HANDLE threadTwo = CreateThread(NULL, 0, ThreadFunc, &playerIDTwo, 0, NULL);

	// Receive until the peer shuts down the connection
	/*	do {
	//spawn a thread to listen to each client seperately
	//an argument to creating a thread will be 1 or 2





	iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
	if (iResult > 0) {
	printf("Bytes received: %d\n", iResult);
	printf("Received:%s\n",recvbuf);
	// Echo the buffer back to the sender
	iSendResult = send( ClientSocket, recvbuf, iResult, 0 );
	if (iSendResult == SOCKET_ERROR) {
	printf("send failed with error: %d\n", WSAGetLastError());
	closesocket(ClientSocket);
	WSACleanup();
	return 1;
	}
	printf("Sent:%s\n",recvbuf);
	printf("Bytes sent: %d\n", iSendResult);
	}
	else if (iResult == 0)
	printf("Connection closing...\n");
	else  {
	printf("recv failed with error: %d\n", WSAGetLastError());
	closesocket(ClientSocket);
	WSACleanup();
	return 1;
	}



	} while (iResult > 0);	*/
	do{
	}while(true);


	return 0;
}
#else
//Mac related stuff
/* Server code in C */
/*
** server.c -- a stream socket server demo
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>

#define PORT "5678"  // the port users will be connecting to
#define DEFAULT_BUFLEN 512
#define BACKLOG 10     // how many pending connections queue will hold

void sigchld_handler(int s)
{
	while(waitpid(-1, NULL, WNOHANG) > 0);
}

// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
	if (sa->sa_family == AF_INET) {
		return &(((struct sockaddr_in*)sa)->sin_addr);
	}

	return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

int main(void)
{
	int sockfd, new_fd,new_fd2;  // listen on sock_fd, new connection on new_fd
	struct addrinfo hints, *servinfo, *p;
	struct sockaddr_storage their_addr; // connector's address information
	socklen_t sin_size;
	struct sigaction sa;
	int yes=1;
	char s[INET6_ADDRSTRLEN];
	int rv;

	memset(&hints, 0, sizeof hints);
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_flags = AI_PASSIVE; // use my IP

	if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) {
		fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
		return 1;
	}

	// loop through all the results and bind to the first we can
	for(p = servinfo; p != NULL; p = p->ai_next) {
		if ((sockfd = socket(p->ai_family, p->ai_socktype,
			p->ai_protocol)) == -1) {
				perror("server: socket");
				continue;
		}

		if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
			sizeof(int)) == -1) {
				perror("setsockopt");
				exit(1);
		}

		if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
			close(sockfd);
			perror("server: bind");
			continue;
		}

		break;
	}

	if (p == NULL)  {
		fprintf(stderr, "server: failed to bind\n");
		return 2;
	}

	freeaddrinfo(servinfo); // all done with this structure

	if (listen(sockfd, BACKLOG) == -1) {
		perror("listen");
		exit(1);
	}

	sa.sa_handler = sigchld_handler; // reap all dead processes
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = SA_RESTART;
	if (sigaction(SIGCHLD, &sa, NULL) == -1) {
		perror("sigaction");
		exit(1);
	}

	printf("server: waiting for connections...\n");

	while(1) {  // main accept() loop
		sin_size = sizeof their_addr;
		new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
		if (new_fd == -1) {
			perror("accept");
			continue;
		}
		if(new_fd>0){
			printf("server: got connection from 1:%s\n", s);
			break;
		}
	}//end of while loop acceping 1st client
	
	while(1) { 
		//try to accept another client
		new_fd2 = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
		if (new_fd2 == -1) {
			perror("accept");
			continue;
		}
		if(new_fd2>0){
			printf("server: got connection from 2:%s\n", s);
			break;
		}
	}//end of while loop for accepting 2nd client
	inet_ntop(their_addr.ss_family,
		get_in_addr((struct sockaddr *)&their_addr),
		s, sizeof s);
	close(sockfd);//dont need this anymore
	int counter=0;//helps tell if the process is for client 1 or 2
	if (!fork()) { // this is the child process will take care of socket1, the main program will do socket2
		//in the new child process, just continue to recv and send
		char buf[DEFAULT_BUFLEN];
		int numbytes;
		//while loop to keep on reciving
		//printf("spawned fork process my counter is:%i",counter);
		counter++;
		do{

			if ((numbytes = recv(new_fd, buf, DEFAULT_BUFLEN-1, 0)) == -1) {
				perror("recv");
				exit(1);
			}
			buf[numbytes] = '\0';
			printf("Received this from Client1:%s\n",buf);
			//print it back to the the client(s)
			if ((numbytes = send(new_fd2, buf, (int) strlen(buf), 0)) == -1) {
				perror("send");
				exit(1);
			}
			printf("Sent this to Client2:%s\n",buf);
		}while(numbytes>0);
		close(new_fd);  // parent doesn't need this

	}//end of fork
	//the main program will listen to socket2 and take care of it
	int runMeForever=0;
	char buf[DEFAULT_BUFLEN];
	int numbytes;
	do{
		if ((numbytes = recv(new_fd2, buf, DEFAULT_BUFLEN-1, 0)) == -1) {
			perror("recv");
			exit(1);
		}
		buf[numbytes] = '\0';
		printf("Received this from Client2:%s\n",buf);
		//print it back to the the client(s)
		if ((numbytes = send(new_fd, buf, (int) strlen(buf), 0)) == -1) {
			perror("send");
			exit(1);
		}
		printf("Sent this to Client1:%s\n",buf);
	}while(numbytes>0);
	close(new_fd2);  // parent doesn't need this
	return 0;
}

#endif